﻿// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.ReflectionModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Internal;
using System.ComponentModel.Composition.Primitives;

namespace System.ComponentModel.Composition.AttributedModel
{
    internal abstract class AttributedImportDefinition : ContractBasedImportDefinition, ICompositionElement
    {
        private readonly string _contractName;
        private readonly ImportAttribute _importAttribute;
        private readonly ImportType _importType;
        private readonly IEnumerable<string> _requiredMetadata;
        private readonly ReflectionItem _item;
        private readonly AttributedComposablePartDefinition _definition;

        public AttributedImportDefinition(AttributedComposablePartDefinition definition, ReflectionItem item, ICustomAttributeProvider attributeProvider)
        {
            Assumes.NotNull(definition, item, attributeProvider);

            this._definition = definition;
            this._item = item;
            this._importType = new ImportType(item.ReturnType);
            this._importAttribute = attributeProvider.GetFirstAttribute<ImportAttribute>() ?? new ImportAttribute();
            this._contractName = CompositionServices.GetContractNameFromImport(this._importAttribute, this._importType.Type);

            this._requiredMetadata = attributeProvider.GetAttributes<ImportRequiredMetadataAttribute>().Select(i => i.Name);

#if !SILVERLIGHT
            if (this._importType.IsLazy)
            {
                this._requiredMetadata = this._requiredMetadata.Concat(CompositionServices.GetRequiredMetadata(this._importType.LazyType.MetadataViewType));
            }
#endif
        }

        public AttributedComposablePartDefinition Definition
        {
            get { return _definition; }
        }

        public ReflectionItem Item
        {
            get { return _item; }
        }

        public override string ContractName
        {
            get { return this._contractName; }
        }

        public override ImportCardinality Cardinality
        {
            get
            {
                if (_importType.IsEnumerable)
                {   
                    // IEnumerable and collections are always 
                    // considered as 'zero or more'
                    return ImportCardinality.ZeroOrMore;
                }

                if (_importAttribute.AllowDefault)
                {
                    return ImportCardinality.ZeroOrOne;
                }

                return ImportCardinality.ExactlyOne;
            }
        }

        public override IEnumerable<string> RequiredMetadata 
        {
            get { return _requiredMetadata; } 
        }

        string ICompositionElement.DisplayName
        {
            get { return GetDisplayName(); }
        }

        ICompositionElement ICompositionElement.Origin
        {
            get { return _definition; }
        }

        public override bool IsRecomposable
        {
            get { return this._importAttribute.AllowRecomposition; }
        }

        public override CreationPolicy RequiredCreationPolicy
        {
            get { return this._importAttribute.RequiredCreationPolicy; }
        }

        public override string ToString()
        {
            return GetDisplayName();
        }

        public abstract ImportingItem ToImportingItem();

        protected abstract string GetDisplayName();        
    }
}
